package com.feng.security.jarsigner;



import java.io.IOException;
import java.io.InputStream;
import java.security.CodeSigner;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;


/**
 * 
 * @author zhangwb1
 * The jarsigner utility.
 *
 * @version 1.0, 07/18/10
 */



public class CheckSigner {
	
	private static final long _25_YEARS = 365 * 25 * 24 * 60 * 60 * 1000L; // milliseconds
	
	private static final long YEAR_BASE = 365 * 1  * 24 * 60 * 60 * 1000L; // milliseconds
	
	public static PublicKey getX509PublicKeyFromCert(Certificate cert){
		return cert.getPublicKey();
	}

	/**
	 * 
	 * @param filePath 文件路径
	 * @param validYears 证书有效期(缺省大于25Y)
	 * @return
	 */
	public static String verify(String filePath,int validYears){
		String verifyed = "00000";
		Throwable mVerifyError = null;
		
		try {

			JarFile jarFile = new JarFile(filePath);
			JarEntry je = null;
			
			PublicKey publicKey = null;

			Enumeration<JarEntry> entries = jarFile.entries();
			byte[] readBuffer = new byte[8192];
			while (entries.hasMoreElements()) {
				je = (JarEntry) entries.nextElement();
				if (je.isDirectory())
					continue;
				if (je.getName().startsWith("META-INF/"))
					continue;
				Certificate[] certs = loadCertificates(jarFile, je, readBuffer);
				CodeSigner[] signers = je.getCodeSigners();
				if(null == signers){
					//未签名
					verifyed = "00004";
					break;
				}
				for (int i = 0; i < signers.length; i++) {
					List<? extends Certificate> certs1 = signers[i].getSignerCertPath().getCertificates();
					for (Certificate c : certs1) {
						X509Certificate x509Cert = (X509Certificate) c;
						if(x509Cert.getSubjectDN().getName().indexOf("CN=Android Debug")>-1){
							//使用Android Debug签名apk包
							return "00001";
						}
						Date notAfter = x509Cert.getNotAfter();
						Date notBefore = x509Cert.getNotBefore();
						if(notAfter.getTime() < notBefore.getTime() + _25_YEARS){
							//签名有效期小于25年
							return "00002";
						}
						if(notAfter.getTime() < System.currentTimeMillis()){
//							签名有效期小于当前日期
							return "00003";
						}
					}
				}
				    														
				if (certs != null && certs.length > 0) {
					final int N = certs.length;
					try {
						for (int i = 0; i < N; i++) {
							publicKey = getX509PublicKeyFromCert(certs[i]);
							certs[i].verify(publicKey);
						}
					} catch (NoSuchAlgorithmException e) {
						mVerifyError = e;
						verifyed = "11111";
					} catch (InvalidKeyException e) {
						mVerifyError = e;
						verifyed = "11111";
					} catch (NoSuchProviderException e) {
						mVerifyError = e;
						verifyed = "11111";
					} catch (SignatureException e) {
						mVerifyError = e;
						verifyed = "11111";
					} catch (CertificateException e) {
						mVerifyError = e;
						verifyed = "11111";
					}
				}else{
					mVerifyError = new Throwable(je.getName() + " has not certificated!");
					verifyed = "11111";
				}
				if("11111".equals(verifyed)){
					break;
				}
			}
			jarFile.close();
		} catch (IOException e) {
			mVerifyError = e;
			verifyed = "11111";
		} catch (Throwable e){
			mVerifyError = e;
			verifyed = "11111";
		}
		return verifyed;
	}
	
	private static X509Certificate readPublicKey(InputStream input) throws IOException,
			GeneralSecurityException {
//		FileInputStream input = new FileInputStream(file);
		try {
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			return (X509Certificate) cf.generateCertificate(input);
		} finally {
			input.close();
		}
	}

	private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
			byte[] readBuffer) {
		try {
			// We must read the stream for the JarEntry to retrieve
			// its certificates.
			InputStream is = jarFile.getInputStream(je);
			while (is.read(readBuffer, 0, readBuffer.length) != -1) {
				// not using
			}
			is.close();
			return je != null ? je.getCertificates() : null;
		} catch (IOException e) {

		}
		return null;
	}
	
	public static void main(String[] args){
		CheckSigner verify =  new CheckSigner();
		String filePtah = "D://upapp/应用包/AnyCut/AnyCut.lca";
		String result = verify.verify(filePtah,5);
		
		System.out.println(result);
	}

}
